#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <cstring>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h>

#define SHM_NAME "/my_shm" // 共享内存对象的名称
#define SHM_SIZE 1024      // 共享内存的大小
int main()
{
    const char *message = "i am process A";
    int shm_fd;
    void *ptr;
    // 创建或打开共享内存
    shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666);
    if (shm_fd == -1)
    {
        perror("shm_open");
        exit(1);
    }

    if (ftruncate(shm_fd, SHM_SIZE) == -1)
    {
        perror("ftruncate");
        exit(1);
    }

    // 映射共享内存到进程的地址空间：PROT_READ | PROT_WRITE 表示：这些是映射区域的保护标志。
    // PROT_READ 表示映射区域可被读取，PROT_WRITE 表示映射区域可被写入。你可以根据需要设置其他保护标志，比如 PROT_EXEC（可执行）或 PROT_NONE（不可访问）。
    // MAP_SHARED:MAP_SHARED 表示对映射区域的写操作将对映射该文件的所有进程可见。也就是说，如果一个进程写入映射区域，这些更改将反映到文件本身，
    // 并且其他映射了同一文件区域的进程也将看到这些更改。
    ptr = mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    if (ptr == MAP_FAILED)
    {
        perror("mmap");
        exit(1);
    }
    memcpy(ptr, message, strlen(message) + 1);
    pid_t id = fork();
    if (id == 0)
    {
        // 子进程
        int shm_fd;
        void *ptr;
        shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDONLY, 0666);
        if (shm_fd == -1)
        {
            perror("shm_open");
            exit(1);
        }
        // 映射共享内存到进程的地址空间
        ptr = mmap(0, SHM_SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);
        if (ptr == MAP_FAILED)
        {
            perror("mmap");
            exit(1);
        }
        // 读取数据
        message = (char *)ptr;
        printf("Received: %s\n", message);
        // 解除映射并关闭共享内存对象
        if (munmap(ptr, SHM_SIZE) == -1)
        {
            perror("munmap");
            exit(1);
        }
        if (close(shm_fd) == -1)
        {
            perror("close");
            exit(1);
        }
        exit(-1);
    }
    sleep(5);
    // 解除映射并关闭共享内存对象
    if (munmap(ptr, SHM_SIZE) == -1)
    {
        perror("munmap");
        exit(1);
    }
    close(shm_fd);
    shm_unlink(SHM_NAME);

    return 0;
}